
import { ObjectId } from 'mongodb'
import { Conditions } from '@/common/util/util.service'
// whereJson装饰器
export const WhereJsonDecorator = (target, key, descriptor) => {
    const originalMethod = descriptor.value;

    descriptor.value = async function (queryConditions) {
        let whereJson = {};
        // 检查 whereJson 是否存在，并处理 _id 字段

        queryConditions.whereJson = transformWhereJsonId(queryConditions.whereJson)

        // 检查whereJson 是否存在条件操作符  链式调用装饰器
        if (queryConditions.whereJson) {
            for (const [field, conditions] of Object.entries(queryConditions.whereJson)) {
                if (typeof conditions === 'object' && (conditions as Conditions).build) {
                    whereJson[field] = (conditions as Conditions).build();
                } else {
                    whereJson[field] = conditions;
                }

            }
        }
        // 调用原始方法
        return await originalMethod.call(this, {
            ...queryConditions, // 保留其他参数
            whereJson,
        });
    };

    return descriptor;
}


// 排序处理装饰器
export const SortArrDecorator = (target, key, descriptor) => {
    const originalMethod = descriptor.value;
    descriptor.value = async function (queryConditions) {
        if ('sortArr' in queryConditions && queryConditions.sortArr.length) {
            queryConditions.sortArr = transformSortArr(queryConditions.sortArr)
        }
        // 调用原始方法
        return await originalMethod.call(this, {
            ...queryConditions, // 保留其他参数
        });
    };

    return descriptor;
}

// getTableData formData根据columns类型数据转换
export const FormDataDecorator = (target, key, descriptor) => {
    const originalMethod = descriptor.value;
    descriptor.value = function (queryConditions) {
        const { columns = [], formData, sortRule = [] } = queryConditions.data;
        queryConditions.sortArr = sortRule.length ? transformSortArr(sortRule) : []
        const whereJson: any = {
            ...queryConditions.whereJson,
        };
        
        columns.forEach((column: any) => {
            const { key, mode} = column;
            const value = formData[key];
            if (value) {
                if (mode === "=") {
                    whereJson[key] = value; // 完全匹配
                }
                
                if (mode === "!=") {
                    whereJson[key] = { $ne: value }; // 不等于
                }
                
                if (mode === "%%") {
                    whereJson[key] = { $regex: value, $options: 'i' }; // 模糊匹配
                }
                
                if (mode === "%*") {
                    whereJson[key] = { $regex: `^${value}`, $options: 'i' }; // 以xxx开头
                }
                
                if (mode === "*%") {
                    whereJson[key] = { $regex: `${value}$`, $options: 'i' }; // 以xxx结尾
                }
                
                if (mode === ">") {
                    whereJson[key] = { $gt: value }; // 大于
                }
                
                if (mode === ">=") {
                    whereJson[key] = { $gte: value }; // 大于等于
                }
                
                if (mode === "<") {
                    whereJson[key] = { $lt: value }; // 小于
                }
                
                if (mode === "<=") {
                    whereJson[key] = { $lte: value }; // 小于等于
                }
                
                if (mode === "in") {
                    whereJson[key] = { $in: value }; // 在数组里
                }
                
                if (mode === "nin") {
                    whereJson[key] = { $nin: value }; // 不在数组里
                }
                
                if (mode === "[]") {
                    whereJson[key] = { $gte: value[0], $lte: value[1] }; // 范围 arr[0] <= x <= arr[1]
                }
                
                if (mode === "[)") {
                    whereJson[key] = { $gte: value[0], $lt: value[1] }; // 范围 arr[0] <= x < arr[1]
                }
                
                if (mode === "(]") {
                    whereJson[key] = { $gt: value[0], $lte: value[1] }; // 范围 arr[0] < x <= arr[1]
                }
                
                if (mode === "()") {
                    whereJson[key] = { $gt: value[0], $lt: value[1] }; // 范围 arr[0] < x < arr[1]
                }
                
                if (mode === "custom") {
                    // 不自动参与 where 条件，跳过处理
                    return;
                }
            }

        });
        queryConditions = { ...queryConditions, whereJson };
        // 调用原始方法，传递修改后的参数
        return originalMethod.call(this, queryConditions);
    };
    return descriptor;
}

// 聚合联表参数处理
export const ForeignDecorator = (target, key, descriptor) => {
    const originalMethod = descriptor.value;

    descriptor.value = async function (queryConditions) {
        let foreignDB = [];

        if (queryConditions.foreignDB) {

            foreignDB = transformForeignDB(queryConditions.foreignDB).reduce((per, item) => {

                try {
                    // 转换所有foreignDB whereJson
                    const whereJson = transformForeignDBWhereJson(item)

                    // 转换所有foreignDB fieldJson
                    const fieldJson = transformFieldJson(item)

                    // 转换所有foreignDB sortArr
                    const sortArr = transformForeignDBSortArr(item)

                    const arr = [
                        (item.dbName ? {
                            $lookup: {
                                from: item.dbName,           // 要联接的目标集合
                                localField: item.localKey,         // 当前集合的字段
                                foreignField: item.foreignKey,   // 目标集合中的字段
                                as: item.as         // 合并到结果中的字段名
                            }
                        } : {}),
                        (whereJson ? { $match: whereJson } : {}),
                        (item.limit ? { $limit: item.limit } : {}),
                        (item.unwind ? { $unwind: { path: '$' + item.as, preserveNullAndEmptyArrays: true } } : {}),
                        (fieldJson ? { $project: fieldJson } : {}),
                        (sortArr ? { $sort: sortArr } : {}),
                    ]
                    return per.concat(arr.filter(item => Object.keys(item).length > 0))
                } catch (e) {
                    console.log('转换错误', e)
                }
            }, [])
        }

        // 调用原始方法
        return await originalMethod.call(this, {
            ...queryConditions, // 保留其他参数
            foreignDB,
        });
    };

    return descriptor;
}

// ForeignDB 转换  递归平铺嵌套的 foreignDB
const transformForeignDB = (data) => {
    let result = [];
    data.forEach(item => {

        const { foreignDB, ...rest } = item;

        result.push(rest);

        if (item.foreignDB && item.foreignDB.length) {
            result = result.concat(transformForeignDB(item.foreignDB)); // 递归平铺嵌套的 foreignDB
        }
    });

    return result;
}

/* 
    ForeignDBsortArr 转换
    {as:'user',sortArr:[{name:'age',type:'desc'}]} => $sort:{user.age:-1}
*/
const transformForeignDBSortArr = (item) => {
    if (!item.sortArr || item.sortArr.length <= 0) return false
    const sortObj = {}
    item.sortArr.forEach(items => {
        sortObj[item.as + '.' + items.name] = items.type === 'desc' ? -1 : 1
    })
    return sortObj
}


/*
    sortArr 转换
    sortArr:[{name:'age',type:'desc'}] => $sort:{age:-1}
*/
const transformSortArr = (sortArr) => {
    if (!sortArr || sortArr.length <= 0) return false
    const sortObj = {}
    sortArr.forEach(items => {
        sortObj[items.name] = items.type === 'desc' ? -1 : 1
    })
    return sortObj
}

/*
    fieldJson 转换
    ForeignDB:{as:'user',fieldJson:{name:1,age:1}} => ForeignDB:{as:'user',fieldJson:{'user.name':1,'user.age':1}}
*/
const transformFieldJson = (item) => {
    // console.log('item', item.fieldJson)
    if (!item.fieldJson || Object.keys(item.fieldJson).length <= 0) return false
    const data = Object.fromEntries(Object.entries(item.fieldJson).map(([key, value]) => [`${item.as}.${key}`, value]))
    console.log("痛苦麻花", data)
    return data
}

const transformForeignDBWhereJson = (item) => {
    if (!item.whereJson || Object.keys(item.whereJson).length <= 0) return false
    const data = Object.fromEntries(Object.entries(item.whereJson).map(([key, value]) => [`${item.as}.${key}`, value]))
    return data
}

/*
    whereJson _id 转换
*/
const transformWhereJsonId = (whereJson) => {
    if (whereJson && typeof whereJson === 'object' && '_id' in whereJson) {
        if((whereJson._id as Conditions).build){
            whereJson._id = whereJson._id.build()
        }else{
            whereJson._id = new ObjectId(whereJson._id);
        }
    }
    return whereJson
}
